package ai;

import java.io.BufferedWriter;
import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileWriter;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class Project1 {

	static String fileName = "aiP1_input2-ansi.txt";
	static File aStarFile = new File(fileName);
	static String fileName2 = "aiP1_input.txt";
	static File regularFile = new File(fileName2);
	static List<String> vertices = new ArrayList<String>();
	static List<City> cities = new ArrayList<City>();
	static List<WeightedEdge> edges = new ArrayList<WeightedEdge>();
	static boolean distanceMode = false;
	static File outputFile = new File("output.txt");

	public static void processLineAstarInput(String line) {
		// if the line starts with a # then it is a comment, skip it
		if (line.subSequence(0, 1).equals("#")) {
			// nothing happens here.
		}
		// if the line starts with --- then it is time to switch to distance
		// mode
		else if (line.equals("---")) {
			// now in distance mode
			distanceMode = true;
		}
		// otherwise, if it is not yet distance mode, collect the lat and long
		// for
		// each city and store it in the list of cities
		else if (distanceMode == false) {
			Scanner scanner = new Scanner(line);

			scanner.useDelimiter("-");

			String cityName = scanner.next().trim();
			String latitude = scanner.next().trim();
			String longitude = scanner.next().trim();
			// currently not looking for duplicate cities

			City newCity = new City(cityName, latitude, longitude);
			cities.add(newCity);
		}
		// this happens when distanceMode == true, start adding edges
		// between cities.
		else {
			Scanner scanner = new Scanner(line);

			scanner.useDelimiter("-");

			String startCity = scanner.next().trim();
			String endCity = scanner.next().trim();
			String distance = scanner.next().trim();

			int startNodeLocation = findCity(startCity);
			int endNodeLocation = findCity(endCity);

			if (startNodeLocation == -1) {
				// System.out.println("Start city of: " + startCity +
				// " not in list.");
				System.out.println("Error!  Start city of: " + startCity);
				System.out
						.println("not in list of cities while creating edges.");
			}
			if (endNodeLocation == -1) {
				// System.out.println("End city of: " + endCity +
				// " not in list.");
				System.out.println("Error!  End city of: " + endCity);
				System.out
						.println("not in list of cities while creating edges.");
			}
			edges.add(new WeightedEdge(startNodeLocation, endNodeLocation,
					Integer.parseInt(distance)));
		}
	}

	public static void processLineRegularInput(String line) {

		Scanner scanner = new Scanner(line);
		scanner.useDelimiter("-");

		String startCity = scanner.next().trim();
		String endCity = scanner.next().trim();
		String distance = scanner.next().trim();

		int startNodeLocation = vertices.indexOf(startCity);
		int endNodeLocation = vertices.indexOf(endCity);

		if (startNodeLocation == -1) {
			// System.out.println("Start city of: " + startCity +
			// " not in list.");
			vertices.add(startCity);
			startNodeLocation = vertices.indexOf(startCity);
		}
		if (endNodeLocation == -1) {
			// System.out.println("End city of: " + endCity + " not in list.");
			vertices.add(endCity);
			endNodeLocation = vertices.indexOf(endCity);
		}

		edges.add(new WeightedEdge(startNodeLocation, endNodeLocation, Integer
				.parseInt(distance)));
	}

	private static int findCity(String cityName) {
		int vectorNumber = -1;
		int citiesSize = cities.size();
		for (int i = 0; i < citiesSize; i++) {
			if (cities.get(i).getCityName().equals(cityName)) {
				vectorNumber = i;
			}
		}
		return vectorNumber;
	}

	private static int findCity(ArrayList<City> externalCities, String cityName) {
		int vectorNumber = -1;
		int externalCitiesSize = externalCities.size();
		for (int i = 0; i < externalCitiesSize; i++) {
			if (externalCities.get(i).getCityName().equals(cityName))
				;
			vectorNumber = i;
		}
		return vectorNumber;
	}

	public static void main(String[] args) throws IOException {
		Scanner scanner = new Scanner(System.in);
		AIGraph<City> aStarGraph;
		AIGraph<String> aiGraph;
		String startCity;
		String endCity;

		boolean exist = outputFile.createNewFile();
		
		
		while (true) {
			System.out.println("Please select an option below: \n" + "1. DFS\n"
					+ "2. BFS\n" + "3. A*\n" + "4. Exit");
			int userInput = scanner.nextInt();
			if (userInput == 1) {
				// clear content
				cities.clear();
				vertices.clear();
				edges.clear();

				// load input to create graph
				Scanner fileScanner = new Scanner(regularFile);

				while (fileScanner.hasNext()) {
					processLineRegularInput(fileScanner.nextLine());
				}

				aiGraph = new AIGraph<String>(edges, vertices);

				Scanner scan = new Scanner(System.in);
				System.out.println("Enter a start City:");
				startCity = scan.next();
				System.out.println("Enter an end City:");
				endCity = scan.next();

				if (!(vertices.contains(startCity) || vertices
						.contains(endCity))) {
					System.out.println("City not in graph.");
					break;
				} else {

					String path = aiGraph.AIdfs(startCity, endCity);
					System.out.println("DFS Path:");
					System.out.println(path);

					FileWriter fstream = new FileWriter("output.txt");
					BufferedWriter out = new BufferedWriter(fstream);
					out.write(path);
					out.close();
				}
			} else if (userInput == 2) {

				System.out.println("BES Search.");
				// clear content
				cities.clear();
				vertices.clear();
				edges.clear();

				// load input to create graph
				Scanner fileScanner = new Scanner(regularFile);

				while (fileScanner.hasNext()) {
					processLineRegularInput(fileScanner.nextLine());
				}

				aiGraph = new AIGraph<String>(edges, vertices);

				Scanner scan = new Scanner(System.in);
				System.out.println("Enter a start City:");
				startCity = scan.next();
				System.out.println("Enter an end City:");
				endCity = scan.next();

				if (!(vertices.contains(startCity) || vertices
						.contains(endCity))) {
					System.out.println("City not in graph.");
					break;
				} else {
					String path = aiGraph.AIbfs(startCity, endCity);
					System.out.println("DFS Path:");
					System.out.println(path);
					

					FileWriter fstream = new FileWriter("output.txt");
					BufferedWriter out = new BufferedWriter(fstream);
					out.write(path);
					out.close();
				}

			} else if (userInput == 3) {
				// clear content
				cities.clear();
				vertices.clear();
				edges.clear();

				// load input to create graph
				Scanner fileScanner = new Scanner(aStarFile);

				while (fileScanner.hasNext()) {
					processLineAstarInput(fileScanner.nextLine());
				}

				aStarGraph = new AIGraph<City>(edges, cities);

				Scanner scan = new Scanner(System.in);
				System.out.println("Enter a start City:");
				startCity = scan.next();
				System.out.println("Enter an end City:");
				endCity = scan.next();

				String path = aStarGraph.AIastar(startCity, endCity);
				System.out.println(path);

				FileWriter fstream = new FileWriter("output.txt");
				BufferedWriter out = new BufferedWriter(fstream);
				out.write(path);
				out.close();
				
			} else if (userInput == 4) {
				System.out.println("End...");
				break;
			}
		}
	}
}